import actionProcTypes
import actionProperties
import batma
import catma
import re
import types
import uthread
import zaction
import ztree
ModifierDataTypes = {0: [('Value', 'F', None)],
 1: [('Attribute', 'I', 'AttributeList'), ('AttrSource', 'I', 'TargetTypeList')],
 2: [('Property', 'S', None)]}

def BuildBatmaPropertyList(propertyDefs):
    todo = []
    for propDef in propertyDefs:
        if (propDef.userDataType == 'Modifier'):
            propDef.dataType = 'I'
            todo.append(propDef)

    for propDef in todo:
        for modTypes in ModifierDataTypes.itervalues():
            for modType in modTypes:
                propertyDefs.append(zaction.ProcPropertyTypeDef(((propDef.name + ' ') + modType[0]), modType[1], userDataType=modType[2], show=False, isPrivate=propDef.isPrivate))



    return propertyDefs



def ModifierWrapperMethod(aobj, label, filterList, propRow, editFlags):
    import attrFilter
    import app.Config as Config
    import app.Select as Select

    def PanelRefresh():
        panel = Jessica['AttributesPanel']
        panel.Freeze()
        Select.SetSelection(Select.GetSelection(), panel.GetId())
        panel.Thaw()


    aobj.StartGroup((label + str(propRow.procID)))
    index = len(filterList)
    filterList.append(attrFilter.DataTypeConversionFilter(propRow, 'propertyBaseType', 'propertyValue'))
    aobj.AddMember(('filterList[%d].viewedValue' % index), label=(label + ' Type'), editflags=editFlags, database=True, types=Config.COMBOBOX, enumerations=[ (modTypes[0][0],
     id,
     '') for (id, modTypes,) in ModifierDataTypes.iteritems() ], func=PanelRefresh)
    if (propRow.propertyValue == None):
        propRow.propertyValue = 0
    modTypes = ModifierDataTypes[int(propRow.propertyValue)]
    for modType in modTypes:
        propName = ((propRow.propertyName + ' ') + modType[0])
        properties = ztree.NodeProperty.GetAllPropertiesByTreeNodeID(propRow.treeNodeID)
        for prop in properties:
            if ((propName == prop.propertyName) and (prop.procID == propRow.procID)):
                actionProperties.AddWrapperComponents(aobj, filterList, prop, editFlags, displayName=propName)
                break


    aobj.EndGroup()



def _BatmaProcNameHelper(displayName, procRow):
    propDict = actionProperties.GetPropertyValueDict(procRow)
    procDef = actionProcTypes.GetProcDef(procRow.procType)
    propDefs = procDef.properties
    propsToEval = []

    def ModifierSub(match):
        name = re.search('\\((.*?)\\)', match.group(0))
        propName = name.group(1)
        if (propName not in propDict):
            return (('(ERR: ' + propName) + ')')
        else:
            typeIdx = propDict[propName]
            if (typeIdx is None):
                typeIdx = 0
            modDataType = ModifierDataTypes[int(typeIdx)]
            modData = modDataType[0]
            propName += (' ' + modData[0])
            return (('%(' + propName) + ')s')


    demodifiedString = re.sub('(%\\([^\\)]*?\\)m)', ModifierSub, displayName)

    def InterpretSub(match):
        name = re.search('\\((.*?)\\)', match.group(0))
        propName = name.group(1)
        if (propName not in propDict):
            return (('(ERR: ' + propName) + ')')
        else:
            for propDef in propDefs:
                if (propDef.name == propName):
                    dictVal = propDict[propName]
                    subString = str(dictVal)
                    if (propDef.userDataType != None):
                        typeInfo = getattr(actionProperties, propDef.userDataType, None)
                        if ((typeInfo is not None) and (types.TupleType == type(typeInfo))):
                            if ('listMethod' == typeInfo[0]):
                                list = typeInfo[1](None)
                            elif ('list' == typeInfo[0]):
                                list = typeInfo[1]
                            else:
                                list = None
                            for tuple in list:
                                (name, val, desc,) = tuple[:3]
                                if (val == dictVal):
                                    subString = str(name)
                                    break

                    return subString

            return (('(ERR: ' + propName) + ')')


    return re.sub('(%\\(.*?\\).)', InterpretSub, demodifiedString)



def BatmaProcNameHelper(displayName):
    return lambda procRow: _BatmaProcNameHelper(displayName, procRow)



def GetBuffList(propRow):
    buffList = batma.Buff.GetActionNameIDMappingList()
    retList = [ (buff[0],
     buff[1],
     '') for buff in buffList ]
    retList.insert(0, (' None', None, ''))
    return retList



def GetCatmaClassList(className):

    def _getClassList(className):
        catma = sm.GetService('catma')
        ax2 = catma.GetAX2()
        catmaTypes = ax2.GetNodeByClassName(className, True)
        return [ (catmaNode.GetNodeName(),
         catmaNode.GetFolderID(),
         '') for catmaNode in catmaTypes ]


    return lambda x: _getClassList(className)



def GetBuffIDByName(name):
    buffDict = {name:id for (name, id,) in batma.Buff.GetActionNameIDMappingList()}
    return buffDict.get(name, 0)


OperationList = [('Add', 0, 'Adds a value to an attribute'),
 ('Subtract', 1, 'Subtracts a value from an attribute'),
 ('Multiply', 2, 'Multiplies a value with an attribute'),
 ('Divide', 3, 'Divides an attribute by a value'),
 ('Change Per Second', 4, 'Changes an attribute by a value every second')]
DamageTypeList = [('Default Damage Type', 0, '')]
ChallengeTypeList = [('Default Challenge Type', 0, '')]
TargetTypeList = [('Me', 0, ''), ('My Target', 1, '')]
ComparisonTypeList = [('Decreasing', 0, ''),
 ('Increasing', 1, ''),
 ('GreaterThan', 2, ''),
 ('LessThan', 3, ''),
 ('NowGreaterThanOrEqual', 4, ''),
 ('NowLessThanOrEqual', 5, '')]
exports = {'actionProperties.Modifier': ('method', ModifierWrapperMethod),
 'actionProperties.BuffList': ('listMethod', GetBuffList),
 'actionProperties.EffectList': ('listMethod', GetCatmaClassList('BatmaEffect')),
 'actionProperties.AttributeList': ('listMethod', GetCatmaClassList('BatmaAttribute')),
 'actionProperties.OperationList': ('list', OperationList),
 'actionProperties.DamageTypeList': ('list', DamageTypeList),
 'actionProperties.ChallengeTypeList': ('list', ChallengeTypeList),
 'actionProperties.TargetTypeList': ('list', TargetTypeList),
 'actionProperties.ComparisonTypeList': ('list', ComparisonTypeList),
 'actionProcTypes.DoBuff': zaction.ProcTypeDef(isMaster=True, procCategory='Batma', displayName=BatmaProcNameHelper('DoBuff %(BuffID)s'), properties=BuildBatmaPropertyList([zaction.ProcPropertyTypeDef('BuffID', 'I', userDataType='BuffList', isPrivate=True)])),
 'actionProcTypes.ApplyEffect': zaction.ProcTypeDef(isMaster=False, procCategory='Batma', displayName=BatmaProcNameHelper('ApplyEffect %(EffectType)i(%(EffectValue)m)'), properties=BuildBatmaPropertyList([zaction.ProcPropertyTypeDef('EffectType', 'I', userDataType='EffectList', isPrivate=True), zaction.ProcPropertyTypeDef('EffectValue', 'M', userDataType='Modifier', isPrivate=True)])),
 'actionProcTypes.WaitForBatmaTime': zaction.ProcTypeDef(isMaster=True, procCategory='Batma', displayName=BatmaProcNameHelper('Wait %(BatmaDuration)m sec'), properties=BuildBatmaPropertyList([zaction.ProcPropertyTypeDef('BatmaDuration', 'M', userDataType='Modifier', isPrivate=True)])),
 'actionProcTypes.WaitForBatmaEvent': zaction.ProcTypeDef(isMaster=True, procCategory='Batma', displayName=BatmaProcNameHelper("Wait for '%(EventName)s'"), properties=BuildBatmaPropertyList([zaction.ProcPropertyTypeDef('EventName', 'S', isPrivate=True)])),
 'actionProcTypes.SendBatmaEvent': zaction.ProcTypeDef(isMaster=True, procCategory='Batma', displayName=BatmaProcNameHelper("SendBatmaEvent '%(EventName)s'"), properties=BuildBatmaPropertyList([zaction.ProcPropertyTypeDef('EventName', 'S', isPrivate=True), zaction.ProcPropertyTypeDef('EventTargetType', 'I', userDataType='TargetTypeList', isPrivate=True)])),
 'actionProcTypes.AttributeCheck': zaction.ProcTypeDef(isMaster=True, procCategory='Batma', displayName=BatmaProcNameHelper('%(AttributeID)s %(AttributeComparisonType)s %(AttributeValue)m on %(AttrSource)s'), properties=BuildBatmaPropertyList([zaction.ProcPropertyTypeDef('AttributeID', 'I', userDataType='AttributeList', isPrivate=True),
                                    zaction.ProcPropertyTypeDef('AttrSource', 'I', userDataType='TargetTypeList', isPrivate=True),
                                    zaction.ProcPropertyTypeDef('AttributeComparisonType', 'I', userDataType='ComparisonTypeList', isPrivate=True),
                                    zaction.ProcPropertyTypeDef('AttributeValue', 'M', userDataType='Modifier', isPrivate=True)])),
 'actionProcTypes.ModifyAttribute': zaction.ProcTypeDef(isMaster=True, procCategory='Batma', displayName=BatmaProcNameHelper('%(Operation)s %(ModifierValue)m to %(AttributeID)s on %(AttrSource)s'), properties=BuildBatmaPropertyList([zaction.ProcPropertyTypeDef('AttributeID', 'I', userDataType='AttributeList', isPrivate=True),
                                     zaction.ProcPropertyTypeDef('AttrSource', 'I', userDataType='TargetTypeList', isPrivate=True),
                                     zaction.ProcPropertyTypeDef('Operation', 'I', userDataType='OperationList', isPrivate=True),
                                     zaction.ProcPropertyTypeDef('ModifierValue', 'M', userDataType='Modifier', isPrivate=True)])),
 'actionProcTypes.DealDamage': zaction.ProcTypeDef(isMaster=True, procCategory='Batma', displayName=BatmaProcNameHelper('Deal %(DamageValue)m to %(TargetType)s'), properties=BuildBatmaPropertyList([zaction.ProcPropertyTypeDef('BuffID', 'I', userDataType='BuffList', default=lambda : GetBuffIDByName('DealDamage'), isPrivate=True),
                                zaction.ProcPropertyTypeDef('DamageValue', 'M', userDataType='Modifier', isPrivate=True),
                                zaction.ProcPropertyTypeDef('DamageType', 'I', userDataType='DamageTypeList', isPrivate=True),
                                zaction.ProcPropertyTypeDef('ChallengeType', 'I', userDataType='ChallengeTypeList', isPrivate=True),
                                zaction.ProcPropertyTypeDef('TargetType', 'I', userDataType='TargetTypeList', isPrivate=True)])),
 'actionProcTypes.IsTargetInBatmaRange': zaction.ProcTypeDef(isMaster=True, isConditional=True, procCategory='Batma', displayName=BatmaProcNameHelper('Target in (%(MinRange)m to %(MaxRange)m) meters'), properties=BuildBatmaPropertyList([zaction.ProcPropertyTypeDef('MinRange', 'M', userDataType='Modifier', isPrivate=True), zaction.ProcPropertyTypeDef('MaxRange', 'M', userDataType='Modifier', isPrivate=True)]))}

